package cn.dglydrpy.study.j2ee.mq.rabbitmq.producer;

import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;

import org.junit.Test;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
/**
 * 订单待支付倒计时，到期取消订单 
 * 1.定期轮询（数据库等）=》 大量无用IO操作，效率低下
 * 2.ScheduledExecutorService =》 在高并发的情况下，不建议使用定时任务去做，太浪费服务器性能
 * 3.RabbitMQ 可以对消息和队列两个维度来设置TTL
 *  通过Queue属性设置，队列中所有消息都有相同的过期时间
 *  对消息自身进行单独设置，每条消息的TTL 可以不同
 *  如果两种方法一起使用，则消息的TTL 以两者之间较小数值为准
 *  如果不设置TTL，则表示此消息不会过期
 *  如果TTL设置为0，则表示除非此时可以直接将消息投递到消费者，否则该消息会被立即丢弃
 * 
 * 
 * @author LY_飘涯
 *
 */
public class TtlWaitingProducer {
    public static void main(String[] args) throws NoSuchAlgorithmException, KeyManagementException, URISyntaxException {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setUri("amqp://admin:147258aaaaa@192.168.80.131:5672/%2f");

        try (final Connection connection = factory.newConnection();
             final Channel channel = connection.createChannel()) {

            Map<String, Object> arguments = new HashMap<>();
//            消息队列中消息过期时间，20s
            arguments.put("x-message-ttl", 20 * 1000);
//            如果消息队列没有消费者，则10s后消息过期，消息队列也删除
//            arguments.put("x-expires", 10 * 1000);
            arguments.put("x-expires", 30 * 1000);

            channel.queueDeclare("queue.ttl.waiting",
                    true,
                    false,
                    false,
                    arguments);

            channel.exchangeDeclare("ex.ttl.waiting",
                    "direct",
                    true,
                    false,
                    null);

            channel.queueBind("queue.ttl.waiting", "ex.ttl.waiting", "key.ttl.waiting");

            final AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder()
                    .contentEncoding("utf-8")
                    .deliveryMode(2)   // 持久化的消息
                    .build();

            channel.basicPublish("ex.ttl.waiting",
                    "key.ttl.waiting",
                    null,
                    "等待的订单号".getBytes("utf-8"));


        } catch (Exception ex) {
            ex.printStackTrace();
        }

    }
    
    @Test
    public void testScheduledExecutorService() throws InterruptedException{
    	SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss"); 
    	
    	// 线程工厂 
    	ThreadFactory factory = Executors.defaultThreadFactory(); 
    	
    	// 使用线程池 
    	ScheduledExecutorService service = new ScheduledThreadPoolExecutor(10, factory); 
    	System.out.println("开始等待用户付款10秒：" + format.format(new Date())); 
    	service.schedule(new Runnable() { 
    		
    		@Override public void run() { 
    			System.out.println("用户未付款，交易取消：" + format.format(new Date())); 
    			
    		}
    	}, 10, TimeUnit.SECONDS); // 等待10s
    	
    	Thread.sleep(11000);
    }


}
